package com.weijie.relaxed.net;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.json.JSONException;
import org.json.JSONObject;

import android.text.TextUtils;

import com.android.volley.AuthFailureError;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Request.Method;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.VolleyLog;
import com.android.volley.toolbox.HttpHeaderParser;
import com.android.volley.toolbox.JsonRequest;
import com.android.volley.toolbox.StringRequest;
import com.weijie.relaxed.utils.CollectUtils;

/** 
 * 请求工厂
 * @author weijie 
 * @version 创建时间：2015年1月10日 上午10:49:40 
 */
public class RequestFactory {

	private static final int DEFAULT_TIME_OUT = 5000;

	/*-------------------------- 返回json的请求 start------------------------------ */

	/**
	 * @param url
	 * @param params
	 * @param listener
	 * @return 
	 */
	public static final <T> JSONObjectRequest createJsonHttpGet(
			String url,
			HashMap<String,T> params,
			HashMap<String,String> headers,
			JsonListener listener){
		return createJsonHttpGet(url, params,headers, listener,null);
	}

	/**
	 * @param url
	 * @param params
	 * @param listener
	 * @return 
	 */
	public static final <T> JSONObjectRequest createJsonHttpGet(
			String url,
			HashMap<String,T> params,
			HashMap<String,String> headers,
			JsonListener listener,
			Object tag){

		String paramsText = wrapParams(params);
		if(!TextUtils.isEmpty(paramsText)){
			url += "?"+paramsText;
		}

		JSONObjectRequest request = new JSONObjectRequest(
				Method.GET, 
				url,
				headers, 
				null, 
				listener!=null?listener.mListener:null, 
						listener!=null?listener.mErrorListener:null);

		if(tag !=null){
			request.setTag(tag);
		}
		return request;
	}

	/**
	 * @param url
	 * @param params
	 * @param listener
	 * @return 
	 */
	public static final <T> JSONObjectRequest createJsonHttpPost(String url,
			HashMap<String, T> params, HashMap<String,String> headers, JsonListener listener) {
		return createJsonHttpPost(url, params, headers, listener, null);

	}

	/**
	 * 
	 * @param url
	 * @param params
	 * @param listener
	 * @param tag
	 * @return
	 */
	public static final <T> JSONObjectRequest createJsonHttpPost(String url,
			HashMap<String, T> params, HashMap<String,String> headers, JsonListener listener, Object tag) {

		JSONObjectRequest request = new JSONObjectRequest(
				Method.POST, 
				url,
				headers, 
				wrapParams(params), 
				listener != null ? listener.mListener: null, 
						listener != null ? listener.mErrorListener: null);

		if (tag != null) {
			request.setTag(tag);
		}

		return request;
	}

	static final class JSONObjectRequest extends JsonRequest<JSONObject> {

		private HashMap<String,String> headers;

		public <T> JSONObjectRequest(
				int method, 
				String url, 
				HashMap<String,String> headers,
				String requestBody,
				com.android.volley.Response.Listener<JSONObject> listener, 
				com.android.volley.Response.ErrorListener errorListener) {

			super(method, url, requestBody, listener, errorListener);
			this.headers = headers;
			//setRetryPolicy(new DefaultRetryPolicy(DefaultRetryPolicy.DEFAULT_TIMEOUT_MS,0,0));
			setRetryPolicy(new DefaultRetryPolicy(DEFAULT_TIME_OUT,0,0));
		}

		@Override
		protected Response<JSONObject> parseNetworkResponse(
				NetworkResponse response) {
			try {
				String jsonString =
						new String(response.data,"utf-8");
				return Response.success(new JSONObject(jsonString),
						HttpHeaderParser.parseCacheHeaders(response));
			} catch (UnsupportedEncodingException e) {
				return Response.error(new ParseError(e));
			} catch (JSONException je) {
				return Response.error(new ParseError(je));
			}
		}

		@Override
		public String getBodyContentType() {
			return "application/x-www-form-urlencoded; charset=utf-8";
		}

		@Override
		public Map<String, String> getHeaders() throws AuthFailureError {
			if(headers!=null){
				return headers;
			}else{
				return super.getHeaders();
			}
		}

	}


	/*-------------------------- 返回json的请求 end------------------------------ */



	/*-------------------------- 返回输入流的请求 start------------------------------ */


	/**
	 * @param url
	 * @param params
	 * @param listener
	 * @return 
	 */
	public static final <T> InputStreamRequest createStreamHttpGet(
			String url,
			HashMap<String,T> params,
			HashMap<String,String> headers,
			InputStreamListener listener){
		return createStreamHttpGet(url, params,headers, listener,null);
	}

	/**
	 * @param url
	 * @param params
	 * @param listener
	 * @return 
	 */
	public static final <T> InputStreamRequest createStreamHttpGet(
			String url,
			HashMap<String,T> params,
			HashMap<String,String> headers,
			InputStreamListener listener,
			Object tag){

		String paramsText = wrapParams(params);
		if(!TextUtils.isEmpty(paramsText)){
			url += "?"+paramsText;
		}

		InputStreamRequest request = new InputStreamRequest(
				Method.GET, 
				url,
				headers, 
				null, 
				listener!=null?listener.mListener:null, 
						listener!=null?listener.mErrorListener:null);

		if(tag !=null){
			request.setTag(tag);
		}
		return request;
	}

	/**
	 * @param url
	 * @param params
	 * @param listener
	 * @return 
	 */
	public static final <T> InputStreamRequest createStreamHttpPost(String url,
			HashMap<String, T> params, HashMap<String,String> headers, InputStreamListener listener) {
		return createStreamHttpPost(url, params, headers, listener, null);

	}

	/**
	 * 
	 * @param url
	 * @param params
	 * @param listener
	 * @param tag
	 * @return
	 */
	public static final <T> InputStreamRequest createStreamHttpPost(String url,
			HashMap<String, T> params, HashMap<String,String> headers, InputStreamListener listener, Object tag) {

		InputStreamRequest request = new InputStreamRequest(
				Method.POST, 
				url,
				headers, 
				wrapParams(params), 
				listener != null ? listener.mListener: null, 
						listener != null ? listener.mErrorListener: null);

		if (tag != null) {
			request.setTag(tag);
		}

		return request;
	}

	static final class InputStreamRequest extends Request<InputStream>{

		/** Charset for request. */
		private static final String PROTOCOL_CHARSET = "utf-8";

		private final com.android.volley.Response.Listener<InputStream> mListener;
		private final String mRequestBody;
		private HashMap<String,String> headers;

		public InputStreamRequest (int method, 
				String url, 
				HashMap<String,String> headers,
				String requestBody,
				com.android.volley.Response.Listener<InputStream> listener, 
				com.android.volley.Response.ErrorListener errorListener) {
			super(method, url, errorListener);
			mListener = listener;
			mRequestBody = requestBody;
			this.headers = headers;
			setRetryPolicy(new DefaultRetryPolicy(DefaultRetryPolicy.DEFAULT_TIMEOUT_MS,0,0));
		}

		@Override
		protected Response<InputStream> parseNetworkResponse(
				NetworkResponse response) {
			//服务端没有设置响应头Conetnt-Type,因此默认ISO-8859-1导致乱码，现在写死UTF-8
			InputStream bais = new ByteArrayInputStream(response.data);
			return Response.success(bais,HttpHeaderParser.parseCacheHeaders(response));
		}

		@Override
		protected void deliverResponse(InputStream response) {
			mListener.onResponse(response);
		}

		@Override
		public String getBodyContentType() {
			//服务端没有处理Content-Type: application/json; charset=utf-8,导致500异常，因此先使用下面这个
			return "audio/mp3";
			//return "image/jpeg";
		}

		@Override
		public Map<String, String> getHeaders() throws AuthFailureError {
			if(headers!=null){
				return headers;
			}else{
				return super.getHeaders();
			}
		}

		/**
		 * @deprecated Use {@link #getBodyContentType()}.
		 */
		@Override
		public String getPostBodyContentType() {
			return getBodyContentType();
		}

		/**
		 * @deprecated Use {@link #getBody()}.
		 */
		@Override
		public byte[] getPostBody() {
			return getBody();
		}

		@Override
		public byte[] getBody() {
			try {
				return mRequestBody == null ? null : mRequestBody.getBytes(PROTOCOL_CHARSET);
			} catch (UnsupportedEncodingException uee) {
				VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s",
						mRequestBody, PROTOCOL_CHARSET);
				return null;
			}
		}

	}

	/*-------------------------- 返回输入流的请求 end------------------------------ */



	/*-------------------------- 返回String的请求 start------------------------------ */

	/**
	 * @param url
	 * @param params
	 * @param listener
	 * @return 
	 */
	public static final <T> JStringRequest createStringHttpGet(
			String url,
			HashMap<String,T> params,
			HashMap<String,String> headers,
			StringListener listener){
		return createStringHttpGet(url, params,headers, listener,null);
	}

	/**
	 * @param url
	 * @param params
	 * @param listener
	 * @return 
	 */
	public static final <T> JStringRequest createStringHttpGet(
			String url,
			HashMap<String,T> params,
			HashMap<String,String> headers,
			StringListener listener,
			Object tag){

		String paramsText = wrapParams(params);
		if(!TextUtils.isEmpty(paramsText)){
			url += "?"+paramsText;
		}

		JStringRequest request = new JStringRequest(
				Method.GET, 
				url,
				headers, 
				listener!=null?listener.mListener:null, 
						listener!=null?listener.mErrorListener:null);

		if(tag !=null){
			request.setTag(tag);
		}
		return request;
	}

	public static final <T> JPostStringRequest createStringHttpPost(
			String url,
			HashMap<String,String> params,
			HashMap<String,String> headers,
			StringListener listener,
			Object tag){

		String paramsText = wrapParams(params);
		if(!TextUtils.isEmpty(paramsText)){
			url += "?"+paramsText;
		}

		JPostStringRequest request = new JPostStringRequest(
				Method.POST, 
				url,
				headers, 
				params,
				listener!=null?listener.mListener:null, 
						listener!=null?listener.mErrorListener:null);

		if(tag !=null){
			request.setTag(tag);
		}
		return request;
	}

	static final class JStringRequest extends StringRequest {
		private HashMap<String,String> headers;

		public JStringRequest(int method, String url,HashMap<String,String> headers, Listener<String> listener,
				ErrorListener errorListener) {
			super(method, url, listener, errorListener);
			this.headers = headers;
			//setRetryPolicy(new DefaultRetryPolicy(DefaultRetryPolicy.DEFAULT_TIMEOUT_MS,0,0));
			setRetryPolicy(new DefaultRetryPolicy(DEFAULT_TIME_OUT,0,0));
		}
		public JStringRequest(String url, HashMap<String,String> headers, Listener<String> listener,
				ErrorListener errorListener) {
			super(Method.GET, url, listener, errorListener);
			this.headers = headers;
			//setRetryPolicy(new DefaultRetryPolicy(DefaultRetryPolicy.DEFAULT_TIMEOUT_MS,0,0));
			setRetryPolicy(new DefaultRetryPolicy(DEFAULT_TIME_OUT,0,0));
		}

		@Override
		public Map<String, String> getHeaders() throws AuthFailureError {
			if(headers!=null) {
				return headers;
			} else {
				return super.getHeaders();
			}
		}
	}

	static final class JPostStringRequest extends StringRequest {
		private HashMap<String,String> headers;
		private HashMap<String,String> params;

		public JPostStringRequest(int method, String url,HashMap<String,String> headers,HashMap<String,String> params, Listener<String> listener,
				ErrorListener errorListener) {
			super(method, url, listener, errorListener);
			this.headers = headers;
			this.params = params;
			//setRetryPolicy(new DefaultRetryPolicy(DefaultRetryPolicy.DEFAULT_TIMEOUT_MS,0,0));
			setRetryPolicy(new DefaultRetryPolicy(DEFAULT_TIME_OUT,0,0));
		}
		public JPostStringRequest(String url, HashMap<String,String> headers,HashMap<String,String> params, Listener<String> listener,
				ErrorListener errorListener) {
			super(Method.GET, url, listener, errorListener);
			this.headers = headers;
			this.params = params;
			//setRetryPolicy(new DefaultRetryPolicy(DefaultRetryPolicy.DEFAULT_TIMEOUT_MS,0,0));
			setRetryPolicy(new DefaultRetryPolicy(DEFAULT_TIME_OUT,0,0));
		}

		@Override
		public Map<String, String> getHeaders() throws AuthFailureError {
			if(headers!=null) {
				return headers;
			} else {
				return super.getHeaders();
			}
		}
		@Override
		public byte[] getBody() throws AuthFailureError {
			
			/*JSONObject jsonParam = new JSONObject();
			try {
				jsonParam.put("username", params.get("username"));
				jsonParam.put("password", params.get("password"));
			} catch (JSONException e) {
				e.printStackTrace();
			}*/
			
			JSONObject jsonParam = CollectUtils.getMap2Json(params);
			
			return jsonParam.toString().getBytes();
		}
	}

	/*-------------------------- 返回String的请求 end------------------------------ */

	/**
	 * @param params
	 * @return
	 */
	private static final <T> String wrapParams(HashMap<String,T> params){
		StringBuilder sb = new StringBuilder();
		if(params!=null && !params.isEmpty()){
			Set<Entry<String, T>> entrySet = params.entrySet();
			for(Entry<String,T> entry:entrySet){
				sb.append("&")
				.append(entry.getKey())
				.append("=")
				.append(entry.getValue());
			}
			sb.deleteCharAt(0);
		}
		return sb.toString();
	}

}
